#import <objc/runtime.h>
#import "MRNavigationController.h"

#pragma mark -
NSString * const kUINavigationItemStatusBarStyle = @"statusBarStyle";

@implementation UINavigationItem (MRNavigationController)
@dynamic alpha, hidden, hidesLine, titleColor, tintColor, barTintColor, statusBarStyle;

- (void)dealloc
{
	[[NSNotificationCenter defaultCenter] removeObserver:self];
	objc_removeAssociatedObjects(self);
}

- (NSString *)language
{
	return objc_getAssociatedObject(self, APPLANGUAGE);
}

- (void)setLanguage:(NSString *)language
{
	objc_setAssociatedObject(self, APPLANGUAGE, language, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
	self.title = L(language);
	
	[[NSNotificationCenter defaultCenter] removeObserver:self];
	if (language)
	{
		[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(didLanguage) name:APPLANGUAGE object:nil];
	}
}

- (void)didLanguage
{
	self.title = L(self.language);
}

//===================================================================
- (void)setHidden:(BOOL)hidden
{
	objc_setAssociatedObject(self, @"hidden", @(hidden), OBJC_ASSOCIATION_RETAIN_NONATOMIC);
}
- (BOOL)hidden
{
	return [objc_getAssociatedObject(self, @"hidden") boolValue];
}

//===================================================================
- (void)setHidesLine:(BOOL)hidesLine
{
	objc_setAssociatedObject(self, @"hidesLine", @(hidesLine), OBJC_ASSOCIATION_RETAIN_NONATOMIC);
}
- (BOOL)hidesLine
{
	return [objc_getAssociatedObject(self, @"hidesLine") boolValue];
}

//===================================================================
- (void)setAlpha:(CGFloat)alpha
{
	objc_setAssociatedObject(self, @"alpha", @(alpha), OBJC_ASSOCIATION_RETAIN_NONATOMIC);
	[[UIApplication sharedApplication].keyWindow.rootViewController setNeedsStatusBarAppearanceUpdate];
}
- (CGFloat)alpha
{
	id obj = objc_getAssociatedObject(self, @"alpha");
	return obj ? [obj floatValue] : 1.f;
}

//===================================================================
- (void)setTintColor:(UIColor *)tintColor
{
	objc_setAssociatedObject(self, @"tintColor", tintColor, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
}
- (UIColor *)tintColor
{
	return objc_getAssociatedObject(self, @"tintColor");
}

//===================================================================
- (void)setTitleColor:(UIColor *)titleColor
{
	objc_setAssociatedObject(self, @"titleColor", titleColor, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
}
- (UIColor *)titleColor
{
	return objc_getAssociatedObject(self, @"titleColor");
}

//===================================================================
- (void)setBarTintColor:(UIColor *)barTintColor
{
	objc_setAssociatedObject(self, @"barTintColor", barTintColor, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
}
- (UIColor *)barTintColor
{
	return objc_getAssociatedObject(self, @"barTintColor");
}

//===================================================================
- (void)setStatusBarStyle:(UIStatusBarStyle)statusBarStyle
{
	objc_setAssociatedObject(self, (__bridge const void *)(kUINavigationItemStatusBarStyle), @(statusBarStyle), OBJC_ASSOCIATION_RETAIN_NONATOMIC);
}
- (UIStatusBarStyle)statusBarStyle
{
	return [objc_getAssociatedObject(self, (__bridge const void *)(kUINavigationItemStatusBarStyle)) intValue];
}

@end

#pragma mark - 导航栏(解决iOS7自动布局问题)
@implementation UINavigationBar (MRNavigationController)

+ (void)load
{
	if (!IOS8)
	{
		Method existing = class_getInstanceMethod(self, @selector(layoutSubviews));
		Method new = class_getInstanceMethod(self, @selector(fsLayoutSubviews));
		
		method_exchangeImplementations(existing, new);
	}
}

- (void)fsLayoutSubviews
{
	[super layoutSubviews];
	[self fsLayoutSubviews];		//执行原始的layoutSubviews
	[super layoutSubviews];
}

@end

#pragma mark - 导航控制器扩展
@implementation UINavigationController (MRNavigationController)
@dynamic panGestureRecognizer;

/*===================================================================
 说明:
    获取导航视图控制器
 备注:
	获取指定级的视图控制器,0本级,1上级...
 ==================================================================*/
- (UIViewController *)lastViewController:(NSUInteger)index
{
    if (self.viewControllers.count > index)
        return self.viewControllers[self.viewControllers.count - index - 1];
    else
        return self.viewControllers.firstObject;
}
- (UIViewController *)lastViewController    //获取上级视图控制器
{
    return [self lastViewController:1];
}

- (void)dealloc
{
	for (UIViewController *vc in self.viewControllers)
		[vc viewWillDealloc];
	
	[self viewWillDealloc];
}

- (UIInterfaceOrientationMask)supportedInterfaceOrientations
{
	return UIInterfaceOrientationMaskAll;
}

/*===================================================================
 说明:
	状态栏样式
 ==================================================================*/
- (UIStatusBarStyle)preferredStatusBarStyle
{
	UIViewController *vc = self.topViewController;
	
	UINavigationItem *item = vc.navigationItem;
	if (!item) return [MRSkinManager skin].statusBarStyle;
	
	//导航栏类型
	NSNumber *n = objc_getAssociatedObject(item, (__bridge const void *)kUINavigationItemStatusBarStyle);
	UIStatusBarStyle style = n ? n.intValue : [MRSkinManager skin].statusBarStyle;
	
	//导航按钮颜色
	NSMutableDictionary *d = [NSMutableDictionary dictionaryWithDictionary:[[UIBarButtonItem appearance] titleTextAttributesForState:UIControlStateNormal]];
	for (UIBarButtonItem *btn in item.leftBarButtonItems)
	{
		d[NSForegroundColorAttributeName] = btn.tintColor ? btn.tintColor : item.tintColor;
		[btn setTitleTextAttributes:d forState:UIControlStateNormal];
	}
	for (UIBarButtonItem *btn in item.rightBarButtonItems)
	{
		d[NSForegroundColorAttributeName] = btn.tintColor ? btn.tintColor : item.tintColor;
		[btn setTitleTextAttributes:d forState:UIControlStateNormal];
	}
	
	if (d)
	{
		self.navigationBar.tintColor = item.tintColor ? item.tintColor : [[UINavigationBar appearance].tintColor colorWithAlphaComponent:.9];
	}
	
	//导航栏标题颜色
	self.navigationBar.titleTextAttributes = item.titleColor ? @{NSForegroundColorAttributeName:item.titleColor} : nil;
	
	//导航栏渲染颜色
	self.navigationBar.barTintColor = item.barTintColor ? item.barTintColor : [UINavigationBar appearance].barTintColor;
	
	//导航栏背景属性
	UIView *view = self.navigationBar.subviews.firstObject;
	[view.subviews enumerateObjectsUsingBlock:^(UIView *v, NSUInteger idx, BOOL *stop) {
		v.alpha  = item.alpha;
		v.hidden = item.hidden;
		
		if ([v isKindOfClass:[UIImageView class]])
		{
			v.hidden = item.hidesLine || item.hidden;
		}
	}];
	
	//标签栏样式
	UITabBarItem *bar = vc.tabBarItem;
	if (bar)
	{
		view = self.tabBarController.tabBar.subviews.firstObject;
		view.hidden = bar.hidden;
		
		[UIView animateWithDuration:.1 animations:^{
			view.alpha = bar.alpha;
		}];
		
		view = self.tabBarController.tabBar.subviews.lastObject;
		if ([view isKindOfClass:[UIImageView class]])
		{
			view.hidden = bar.hidesLine || bar.hidden;
		}
		
		self.tabBarController.tabBar.barTintColor = bar.barTintColor ? bar.barTintColor : [UITabBar appearance].barTintColor;
	}
	
	return style;
}

@end

#pragma mark -
@interface MRNavigationController ()

@property (nonatomic) UINavigationControllerOperation		operation;

@end

@implementation MRNavigationController

/*===================================================================
 说明:
    初始根视图
 ==================================================================*/
- (void)viewDidLoad
{
    [super viewDidLoad];
	self.interactivePopGestureRecognizer.enabled = NO;
	
	_shadow = [[UIImageView alloc] initWithImage:IMG(@"pageShadow")];
	
	_shadowView = [[UIView alloc] initWithFrame:self.view.bounds];
	_shadowView.backgroundColor = rgba(0, 0, 0, .2);
	
	[_shadowView addSubview:_shadow];
	
	//
    _panGestureRecognizer = [[UIScreenEdgePanGestureRecognizer alloc] initWithTarget:self action:@selector(panGestureRecognizer:)];
	_panGestureRecognizer.edges = UIRectEdgeLeft;
	_panGestureRecognizer.delegate = self;
    [self.view addGestureRecognizer:_panGestureRecognizer];
}

- (void)viewWillAppear:(BOOL)animated
{
	[self.topViewController viewWillAppear:animated];
	[super viewWillAppear:animated];
}

#pragma mark - 栈管理
/*===================================================================
 说明:
    压入视图
 ==================================================================*/
- (void)pushViewController:(UIViewController *)viewController animated:(BOOL)animated
{
	if (!viewController) return;
	
    //若控制器无返回目的，则置为当前控制器的返回目的
    if (viewController.backViewController == nil)
        viewController.backViewController = self.topViewController.backViewController;
	
	//使用自定义动画PUSH
	if (animated)
	{
		self.operation = UINavigationControllerOperationPush;
		[self startInteractive:viewController];
		[self finishInteractive:YES];
	}
	else
	{
		[super pushViewController:viewController animated:animated];
	}
}

- (void)pushViewController:(UIViewController *)target
{
	[self pushViewController:target animated:YES];
}

/*===================================================================
 说明:
    弹出视图
 ==================================================================*/
- (UIViewController *)popViewControllerAnimated:(BOOL)animated
{
	if (self.topViewController.backViewController)
		return [self popToViewController:self.topViewController.backViewController animated:animated].firstObject;
	else if (self.viewControllers.count > 1)
		return [self popToViewController:self.viewControllers[self.viewControllers.count-2] animated:animated].firstObject;
	else
		return nil;
}

- (NSArray*)popToRootViewControllerAnimated:(BOOL)animated
{
    return [self popToViewController:self.viewControllers.firstObject animated:animated];
}

- (NSArray *)popToViewController:(UIViewController *)viewController animated:(BOOL)animated
{
    if ([self.viewControllers containsObject:viewController])
    {
		for (NSUInteger i=self.viewControllers.count-1; i; i--)
		{
			UIViewController *vc = self.viewControllers[i];
			if (vc == viewController) break;
			
			[vc viewWillDealloc];
		}
		
		//使用自定义动画实现POP
		if (animated && self.operation == UINavigationControllerOperationNone)
		{
			self.operation = UINavigationControllerOperationPop;
			[self startInteractive:viewController];
			[self finishInteractive:YES];
		}
		else if (self.operation == UINavigationControllerOperationNone)
		{
			return [super popToViewController:viewController animated:animated];
		}
    }
	
    return nil;
}

#pragma mark - 交互处理
/*===================================================================
 说明:
	开始交互
 ==================================================================*/
- (void)startInteractive:(UIViewController *)viewController
{
	_origin = self.viewControllers;
	
	//动画目标视图（有标签控制器时依情况使用标签控制器视图作为根视图）
	_mainview = self.view;
	if (self.tabBarController.tabBar.hidden) _mainview = self.tabBarController.view;
	else if (self.tabBarController && viewController.hidesBottomBarWhenPushed) _mainview = self.tabBarController.view;
	
	//目标导航控制器集
	NSInteger i = 0;
	NSArray *target;
	
	if (self.operation == UINavigationControllerOperationPop)
	{
		NSRange range = NSMakeRange(0, [self.viewControllers indexOfObject:viewController] + 1);
		target = [self.viewControllers subarrayWithRange:range];
	}
	else		//PUSH
	{
		i = 1;
		target = [self.viewControllers arrayByAddingObject:viewController];
	}
	
	//截取当前视图
	_target[i] = [_mainview snapshotViewAfterScreenUpdates:NO];
	_target[i].frame = _mainview.superview.bounds;
	[_mainview.superview addSubview:_target[i]];
	
	//目标控制器组
	[self setViewControllers:target animated:NO];
	
	_target[1-i] = [_mainview snapshotViewAfterScreenUpdates:YES];
	_target[1-i].frame = _mainview.superview.bounds;
	
	[_mainview.superview addSubview:_target[1-i]];
	
	//
	if (self.operation == UINavigationControllerOperationPop)
	{
		[_mainview.superview bringSubviewToFront:_target[i]];
		[self updateInteractive:0];
	}
	else	//PUSH
	{
		[_mainview.superview bringSubviewToFront:_target[1-i]];
		[self updateInteractive:1];
	}
	
	//阴影
	[_target[0] addSubview:_shadowView];
	_shadowView.frame = CGRectOffset(_target[0].bounds, -_target[0].bounds.size.width, 0);
	_shadow.frame = CGRectMake(_target[0].bounds.size.width-_shadow.image.size.width, 0, _shadow.image.size.width, _target[0].bounds.size.height);
	
	_mainview.hidden = YES;
}

/*===================================================================
 说明:
    更新交互进度
 ==================================================================*/
- (void)updateInteractive:(CGFloat)percent
{
	CGSize size = self.view.frame.size;
	
	//底图(POP时为目标视图)
	_target[1].center = CGPointMake(-size.width * ((1 - percent) / 3 - .5), _target[1].center.y);
	
	//前图(POP时为旧视图)
	_target[0].center = CGPointMake((percent + .5) * size.width, _target[0].center.y);
	
	_shadowView.alpha = 1 - percent;
}

/*===================================================================
 说明:
    完成交互
 ==================================================================*/
- (void)finishInteractive:(BOOL)finished
{
	if (!finished) [self setViewControllers:_origin animated:NO];
	
	[UIView animateWithDuration:.25 /*delay:0 options:UIViewAnimationOptionCurveEaseOut*/ animations:^{
		
		if (self.operation == UINavigationControllerOperationPop)
			[self updateInteractive:finished ? 1 : 0];
		else if (self.operation == UINavigationControllerOperationPush)
			[self updateInteractive:finished ? 0 : 1];
		
	} completion:^(BOOL finished) {
		
		_mainview.hidden = NO;
		
		[_shadowView removeFromSuperview];
		[_target[0] removeFromSuperview];
		[_target[1] removeFromSuperview];
		
		_origin = nil;
		if (self.operation == UINavigationControllerOperationPush)
		{
			[self.topViewController viewDidPushed:YES];
		}
		self.operation = UINavigationControllerOperationNone;
	}];
}

#pragma mark - 手势处理
/*===================================================================
 说明:
    检测是否可以滑动到菜单
 ==================================================================*/
- (BOOL)gestureRecognizerShouldBegin:(UIGestureRecognizer *)gestureRecognizer
{
    if (gestureRecognizer == _panGestureRecognizer)
    {
        UIBarButtonItem *barItem = self.topViewController.navigationItem.leftBarButtonItem;
        if (barItem == nil || !barItem.enabled || barItem.tag == -1) return NO;
        
        return (self.viewControllers.count > 1);
    }
	
    return YES;
}

/*===================================================================
 说明:
    滑屏手势
 ==================================================================*/
- (void)panGestureRecognizer:(UIPanGestureRecognizer *)gestureRecognizer
{
	static __weak UIViewController *vc = nil;
	
    CGPoint translation = [gestureRecognizer translationInView:gestureRecognizer.view];
	CGFloat progress = translation.x / gestureRecognizer.view.bounds.size.width;
    
    if (gestureRecognizer.state == UIGestureRecognizerStateBegan)
    {
		vc = self.topViewController;
		
		UIViewController *viewController = self.topViewController.backViewController;
		if (!viewController) viewController = self.viewControllers[self.viewControllers.count - 2];
		
		/*if ([gestureRecognizer locationInView:gestureRecognizer.view].x >= gestureRecognizer.view.bounds.size.width / 2)
			_operation = UINavigationControllerOperationPush;
		else*/
			self.operation = UINavigationControllerOperationPop;
		
		[self startInteractive:viewController];
    }
    else if (gestureRecognizer.state == UIGestureRecognizerStateChanged)
    {
		[UIView animateWithDuration:.1 delay:0 options:UIViewAnimationOptionCurveLinear animations:^{
			
			if (self.operation == UINavigationControllerOperationPop)
				[self updateInteractive:MAX(0, progress)];
			else
				[self updateInteractive:MAX(0, progress)];
			
		} completion:nil];
    }
    else if (gestureRecognizer.state == UIGestureRecognizerStateEnded && ABS(progress) >= .4)
	{
		[vc cancel];	//执行当前页面返回
		vc = nil;
		
		//释放
		for (NSUInteger i=_origin.count-1; i; i--)
		{
			if (_origin[i] == self.topViewController) break;
			
			[_origin[i] viewWillDealloc];
		}
		
		[self finishInteractive:YES];
	}
	else
	{
		[self finishInteractive:NO];
	}
}

@end

#pragma mark -
@implementation UIViewController (MRNavigationController)

- (void)viewDidPushed:(BOOL)animated
{
	//
}

@end
